<template>
	<n-collapse-transition>
		<div class="audio-preview-wrapper" v-show="visible">
            <img class="audio-background" :src="musicImgUrl" alt="背景图" />
			<!-- 右上角操作 -->
			<div class="operate-box">

            <n-icon
                @click="handleClosePreview"
                size = '36px'
            >
              <close/>
            </n-icon>
			</div>
            <AudioPlayer
                :option="audioOption"
            />
		</div>
	</n-collapse-transition>
</template>
<script lang="ts" setup>
import {computed, ref, watch} from "vue";
import defaultMusicPng from '@/assets/images/file/file_music.png';
// import activePlayerIcon from '@/assets/images/audio/wave.gif';
import {fileController} from '@/api/file/fileController'
import * as Base64 from 'js-base64'
//@ts-ignore
import fileFunction from '@/libs/globalFunction/file.js'
import {Close} from "@vicons/ionicons5";
import AudioPlayer from "vue3-audio-player";
/**音频组件是否可见**/
const visible = ref(false)
/**当前打开的索引**/
const activeIndex = ref(0)
/**音频播放的循环模式**/
const cycleType = ref(1)


const cycleTypeMap = {
  1: {
    icon: 'icon-xunhuanbofang',
    text: '列表循环'
  },
  2: {
    icon: 'icon-danquxunhuan1',
    text: '单曲循环'
  },
  3: {
    icon: 'icon-suijibofang1',
    text: '随机播放'
  }
}

//  是否正在播放
const isPlay = ref(false)
//  当前播放的秒
const currentTime = ref(0)
//  是否正在拖拽播放进度滑块
const isDrop = ref(false)
//  音量
const volume = ref(0)
//  音频信息
const audioInfo = ref({})
//  歌词列表
const lyricsList = ref([])
//  当前高亮的歌词行索引，从 0 开始
const currentLyricsLineIndex = ref(0)
const loading = ref(false)

const audioList = ref([])

const audioRef = ref(null)

const lyricsListRef = ref(null)

const lyricsLineRef = ref(null)


const defaultIndex = ref(0)
// 当前显示的文件信息
const activeFileObj = computed(() => {
  const res = audioList.value.length ? audioList.value[activeIndex.value] : {}
  return res
})

// 隐藏的 audio 标签
const audioElement = computed(() => {
  return audioRef
})

// 歌曲封面
const musicImgUrl = computed(() => {
  return audioInfo.albumImage
      ? `data:image/jpeg;base64,${audioInfo.albumImage}`
      : defaultMusicPng
})

// 播放进度条步长
const progressStep = computed(() => {
  return audioInfo.duration / 100
})


watch(visible, (newValue) => {
 if(newValue){
   activeIndex.value = defaultIndex.value
 }
})


/**
 * 点击暂停图标触发
 * @description 暂停音频
 */
const handleClickPauseIcon = ()=> {
  isPlay.value = false
  audioRef.pause()
}


/**
 * 将秒转化为时分秒
 * @param {number} duration 总秒数
 */
const transferSecondsToTime  = (duration:number) => {
  const hour = Math.floor(duration / 3600)
  const minutes = Math.floor(duration / 60)
  const seconds = Math.ceil(duration % 60)
  return `${hour < 10 ? `0${hour}` : hour}:${
      minutes < 10 ? `0${minutes}` : minutes
  }:${seconds < 10 ? `0${seconds}` : seconds}`
}
/**
 * 将分秒转化为秒
 * @param {string} time 分秒，格式 00:00
 */
const transferTimeToSeconds = (time:string) =>{
  const timeList = time.split('.')[0].split(':')
  return Number(timeList[1]) + Number(timeList[0]) * 60
}


// 关闭音频预览
const handleClosePreview= () => {
  visible.value = false
}

/**
 * 当前播放时间改变时触发
 */
const handleTimeUpdate = (event) => {
  // 如果正在拖拽进度滑块，函数结束，不计算当前时间
  if (isDrop.value) return
  currentTime.value = event.target.currentTime
  if (lyricsList.value.length) {
    // 遍历歌词，当前秒对应的歌词整行添加高亮效果
    lyricsList.value.forEach((item, index) => {
      if (
          item.startSeconds <= currentTime.value &&
          currentTime.value < item.endSeconds &&
          currentLyricsLineIndex.value !== index
      ) {
        // 确定高亮歌词行索引
        currentLyricsLineIndex.value = index
        // 使高亮歌词行永远保持在第二行
        if (currentLyricsLineIndex.value > 2) {
          // 平滑滚动
          lyricsListRef.scrollTo({
            top: lyricsLineRef.value[index].clientHeight * (index - 2),
            behavior: 'smooth'
          })
        }
      }
    })
  }
}

/**
 * 点击播放图标触发
 * @description 开始播放音频
 */
const handleClickPlayIcon= () => {
  isPlay.value = true
  audioRef.value.play()
}


/**
 * 获取播放器参数
 */
const handleLoadedmetadata = (event)=> {
  const audioDom = event.target
  volume.value = audioDom.volume || 0.5
  currentTime.value = audioDom.currentTime
  handleClickPlayIcon()
}
/**
 * 获取文件信息
 */
const getFileDetailData = () => {
  handleClickPauseIcon()
  loading.value = true
  fileController.getFileDetail({ userFileId: activeFileObj.userFileId })
      .then((res) => {
        loading.value = false
        if (res.code === 200) {
          audioInfo.value = {
            ...res.data.music,
            duration: res.data.music.trackLength
          }
          // Base64 解码为 lrc 格式的歌词文件
          let lyricsStr = Base64.decode(audioInfo.value.lyrics)
          if (lyricsStr.includes('[offset:0]')) {
            // 有歌词，从标志位 [offset:0] 下一行开始截取
            lyricsStr = lyricsStr.split('[offset:0]\n')[1]
          }
          lyricsList.value = lyricsStr
              .split('\n')
              .map((item) => {
                const line = item.split('[')[1].split(']')
                return {
                  time: line[0], //  当前行歌词开始播放的秒数
                  text: line[1] //  当前歌词文本
                }
              })
              .filter((item) => item.text !== '')
          lyricsList.value = lyricsList.value.map((item, index) => {
            return {
              ...item,
              // 当前行歌词起始秒数
              startSeconds: transferTimeToSeconds(item.time),
              // 当前行歌词结束秒数
              endSeconds:
                  index < lyricsList.value.length - 1
                      ? transferTimeToSeconds(
                          lyricsList.value[index + 1].time
                      )
                      : audioInfo.duration
            }
          })
          // 当切换完歌曲时，歌词重新滚动到顶部
          lyricsListRef.scrollTo({
            top: 0,
            behavior: 'smooth'
          })
          currentLyricsLineIndex.value = 0
        }
      })
      .catch(() => {
        loading.value = false
      })
}


/**
 * 切换、暂停或播放歌曲
 * @param {string} type pre - 上一首 | next - 下一首 | manual 手动切换
 * @param {number} index 手动切换的音频索引，从 0 开始
 */
const handleChangeAudioIndex =(type:string, index:number)=> {
  // 如果当前手动切换
  if (type === 'manual') {
    if (activeIndex.value === index) {
      if (isPlay.value) {
        handleClickPauseIcon()
      } else {
        handleClickPlayIcon()
      }
    } else {
      activeIndex.value = index
    }
  } else {
    handleClickPauseIcon()
    // 判断当前循环播放类型
    switch (cycleType.value) {
      case 3: {
        let activeIndex_ = 0
        do {
          activeIndex_ =
              Math.floor(Math.random() * (audioList.value.length - 1)) + 1
        } while (activeIndex.value === activeIndex_)
        activeIndex.value = activeIndex_
        break
      }
      default: {
        if (type === 'pre') {
          if (activeIndex.value === 0) {
            activeIndex.value = audioList.value.length - 1
          } else {
            activeIndex.value--
          }
        } else if (type === 'next') {
          if (activeIndex.value === audioList.value.length - 1) {
            activeIndex.value = 0
          } else {
            activeIndex.value++
          }
        }
        break
      }
    }
  }
}


const handleChangeProgress  = (progress:number)=> {
  audioRef.value.currentTime = progress
  isDrop.value = false
}

/**
 * 切换循环播放类型
 */
const handleChangeCycleType = () =>{
  if (cycleType.value === 3) {
    cycleType.value = 1
  } else if (cycleType.value >= 1) {
    cycleType.value++
  }
}

const musicShow = (audioList_:[],defaultIndex_: number) => {
  visible.value = true
  audioList.value = audioList_
  defaultIndex.value = defaultIndex_
}

defineExpose({
  musicShow
})


</script>

<style >
.audio-preview-wrapper {
  background: $PrimaryText;
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  z-index: 3;
  color: $BorderBase;
}
.audio-preview-wrapper .audio-background {
  position: fixed;
  top: -50%;
  left: 0;
  width: 100vw;
  height: auto;
  filter: blur(65px);
  opacity: 0.6;
  z-index: -1;
}
.audio-preview-wrapper .operate-box {
  position: fixed;
  top: 16px;
  right: 32px;
  display: flex;
  align-items: center;
}
.audio-preview-wrapper .operate-box .tip-icon,
.audio-preview-wrapper .operate-box .close-icon {
  margin-left: 16px;
  cursor: pointer;
}
.audio-preview-wrapper .operate-box .tip-icon:hover,
.audio-preview-wrapper .operate-box .close-icon:hover {
  color: $Warning;
}
.audio-preview-wrapper .operate-box .tip-icon {
  font-size: 26px;
}
.audio-preview-wrapper .operate-box .close-icon {
  font-size: 30px;
}
.audio-preview-wrapper .audio-list-wrapper {
  margin: 0 auto;
  width: 85%;
  height: calc(100vh - 120px);
  padding-top: 32px;
  display: flex;
  justify-content: space-between;
}
.audio-preview-wrapper .audio-list-wrapper .audio-list {
  flex: 1;
  list-style: none;
}
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-list-body {
  height: calc(100% - 56px);
  overflow: auto;
}
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-list-header,
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-item {
  border-radius: 8px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 56px;
  cursor: pointer;
  padding: 0 16px;
}
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-list-header:hover,
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-item:hover {
  background: rgba(0,0,0,0.1);
}
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-list-header.active,
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-item.active {
  background: rgba(0,0,0,0.1);
  color: $Warning;
}
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-list-header .name,
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-item .name {
  flex: 1;
}
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-list-header .name .sequence,
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-item .name .sequence {
  display: inline-block;
  margin-right: 8px;
  width: 14px;
  text-align: center;
}
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-list-header .name .wave,
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-item .name .wave {
  margin-right: 10px;
  width: 12px;
  height: 12px;
}
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-list-header .name .no-wave,
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-item .name .no-wave {
  margin-right: 6px;
  font-size: 16px;
}
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-list-header .play-icon,
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-item .play-icon,
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-list-header .pause-icon,
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-item .pause-icon,
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-list-header .download-icon,
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-item .download-icon,
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-list-header .share-icon,
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-item .share-icon {
  margin-right: 16px;
  font-size: 22px;
  cursor: pointer;
}
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-list-header .play-icon:hover,
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-item .play-icon:hover,
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-list-header .pause-icon:hover,
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-item .pause-icon:hover,
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-list-header .download-icon:hover,
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-item .download-icon:hover,
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-list-header .share-icon:hover,
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-item .share-icon:hover {
  color: $Warning;
}
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-list-header .download,
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-item .download {
  color: inherit;
}
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-list-header .download:hover,
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-item .download:hover {
  color: $Warning;
}
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-list-header .audio-size,
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-item .audio-size {
  width: 120px;
  padding-right: 24px;
  text-align: right;
}
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-list-header .path,
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-item .path {
  min-width: 120px;
}
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-list-header {
  padding-right: 24px;
}
.audio-preview-wrapper .audio-list-wrapper .audio-list .audio-list-header .name {
  padding-left: 18px;
}
.audio-preview-wrapper .audio-list-wrapper .img-and-lyrics {
  padding: 8px 0 0 16px;
  width: 340px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.audio-preview-wrapper .audio-list-wrapper .img-and-lyrics .audio-img {
  margin-bottom: 16px;
  width: 160px;
  height: 160px;
}
.audio-preview-wrapper .audio-list-wrapper .img-and-lyrics .audio-name {
  margin-bottom: 8px;
  font-size: 18px;
  line-height: 2;
}
.audio-preview-wrapper .audio-list-wrapper .img-and-lyrics .album-artist,
.audio-preview-wrapper .audio-list-wrapper .img-and-lyrics .album-name {
  margin-bottom: 8px;
}
.audio-preview-wrapper .audio-list-wrapper .img-and-lyrics .lyrics-list {
  width: 100%;
  flex: 1;
  overflow: auto;
-webkit-mask-image: linear-gradient(180deg, rgba(255,255,255,0) 0, rgba(255,255,255,0.6) 15%, #fff 25%, #fff 75%, rgba(255,255,255,0.6) 85%, rgba(255,255,255,0));
}
.audio-preview-wrapper .audio-list-wrapper .img-and-lyrics .lyrics-list.one .lyrics-item {
  margin-top: 40px;
}
.audio-preview-wrapper .audio-list-wrapper .img-and-lyrics .lyrics-list .lyrics-item {
  line-height: 40px;
  cursor: pointer;
}
.audio-preview-wrapper .audio-list-wrapper .img-and-lyrics .lyrics-list .lyrics-item:not(.active):hover {
  color: #fff;
}
.audio-preview-wrapper .audio-list-wrapper .img-and-lyrics .lyrics-list .lyrics-item.active {
  color: $Warning;
}
.audio-preview-wrapper .control-wrapper {
  margin: 0 auto;
  width: 85%;
  height: 120px;
  padding: 24px 0 32px 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.audio-preview-wrapper .control-wrapper .control-left {
  flex: 1;
  height: 100%;
  display: flex;
  align-items: center;
  text-align: center;
  padding-left: 8px;
}
.audio-preview-wrapper .control-wrapper .control-left .operate-icon {
  margin-right: 16px;
  font-size: 40px;
  cursor: pointer;
}
.audio-preview-wrapper .control-wrapper .control-left .operate-icon:hover {
  color: $Warning;
}
.audio-preview-wrapper .control-wrapper .control-left .progress-bar {
  margin-right: 16px;
  flex: 1;
}
.audio-preview-wrapper .control-wrapper .control-left .progress-bar >>> .el-slider__runway {
  height: 2px;
}
.audio-preview-wrapper .control-wrapper .control-left .progress-bar >>> .el-slider__runway .el-slider__button-wrapper {
  top: -17px;
}
.audio-preview-wrapper .control-wrapper .control-left .progress-bar >>> .el-slider__runway .el-slider__button-wrapper .el-slider__button {
  border: none;
}
.audio-preview-wrapper .control-wrapper .control-left .progress-bar >>> .el-slider__runway .el-slider__bar {
  height: 100%;
  background: $Warning;
}
.audio-preview-wrapper .control-wrapper .control-right {
  width: 340px;
  font-size: 24px;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 32px;
}
.audio-preview-wrapper .control-wrapper .control-right .operate-icon {
  margin-right: 16px;
  cursor: pointer;
}
.audio-preview-wrapper .control-wrapper .control-right .operate-icon:nth-last-of-type {
  margin-right: 0;
}
.audio-preview-wrapper .control-wrapper .control-right .operate-icon:hover {
  color: $Warning;
}
.audio-preview-wrapper .control-wrapper .control-right .operate-icon.download-link {
  font-size: 32px;
  color: inherit;
}
.audio-preview-wrapper .control-wrapper .control-right .operate-icon.download-link:hover .download-icon {
  color: $Warning;
}
.audio-preview-wrapper .control-wrapper .control-right .volume-icon {
  margin-right: 8px;
}
.audio-preview-wrapper .control-wrapper .control-right .volume-bar {
  width: 100px;
}
.audio-preview-wrapper .control-wrapper .control-right .volume-bar >>> .el-slider__runway {
  height: 2px;
}
.audio-preview-wrapper .control-wrapper .control-right .volume-bar >>> .el-slider__runway .el-slider__button-wrapper {
  top: -19px;
}
.audio-preview-wrapper .control-wrapper .control-right .volume-bar >>> .el-slider__runway .el-slider__button-wrapper .el-slider__button {
  border: none;
}
.audio-preview-wrapper .control-wrapper .control-right .volume-bar >>> .el-slider__runway .el-slider__bar {
  height: 100%;
  background: $Warning;
}

</style>
